﻿
// OPOSADKDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "OPOSADK.h"
#include "OPOSADKDlg.h"
#include "afxdialogex.h"
#include "Opos.hi"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#pragma warning (disable:4996)

#define VENDOR_WEB_SITE           _T("http://www.honglitek.com/")

// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
    CAboutDlg();

    // 对话框数据
    enum { IDD = IDD_ABOUTBOX };

protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

    // 实现
protected:
    DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// COPOSADKDlg 对话框
#include <string>
using namespace std;



COPOSADKDlg::COPOSADKDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(COPOSADKDlg::IDD, pParent)
{

    m_hRootKey = NULL;
    m_hClassKey = NULL;
    m_hServiceKey = NULL;

    m_hIcon = AfxGetApp()->LoadIcon(IDB_BITMAP_MAIN);//(//IDR_MAINFRAME);
#ifdef __DEBUG_LOG__
   InitLogger(ALL_LEVEL, FILE_EXECUTOR, L"C:\\HongliTeck_Debug");
    LOG_DEBUG(_T("HongliTeck OPOS ADK (V0.1) start, main frame created."));
    int nLog = 2;
    Log(DEBUG_LEVEL, EOPOSADK, _T("OPOS ADK start ! %d."), nLog);
#endif

    m_pCheckDlg  = NULL;
}

void COPOSADKDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_LIST_DEVICES, m_lstDevices);
    DDX_Control(pDX, IDC_TREE_DEVICES, m_treeDevices);
}

BEGIN_MESSAGE_MAP(COPOSADKDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BTN_ADD, &COPOSADKDlg::OnBnClickedBtnAdd)
    ON_BN_CLICKED(IDC_BTN_CHECK, &COPOSADKDlg::OnBnClickedBtnCheck)
    ON_NOTIFY(TVN_SELCHANGED, IDC_TREE_DEVICES, &COPOSADKDlg::OnTvnSelchangedTreeDevices)
    ON_BN_CLICKED(IDC_BTN_DELETE, &COPOSADKDlg::OnBnClickedBtnDelete)
    ON_NOTIFY(NM_CLICK, IDC_SYSLINK1, &COPOSADKDlg::OnNMClickSyslink1)
END_MESSAGE_MAP()


// COPOSADKDlg 消息处理程序

BOOL COPOSADKDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // 将“关于...”菜单项添加到系统菜单中。

    // IDM_ABOUTBOX 必须在系统命令范围内。
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // 设置此对话框的图标。当应用程序主窗口不是对话框时，框架将自动
    //  执行此操作
    SetIcon(m_hIcon, TRUE);			// 设置大图标
    SetIcon(m_hIcon, FALSE);		// 设置小图标

    // TODO: 在此添加额外的初始化代码

    InitInstallPath();

    QueryDeviceName(_T(OPOS_CLASSKEY_SCAN));

    GetDlgItem(IDC_BTN_DELETE)->EnableWindow(FALSE);
    GetDlgItem(IDC_BTN_CHECK)->EnableWindow(FALSE);

    GetDlgItem(IDC_STATIC_DEVLDN)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_STATIC_DEVNAME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_STATIC_DEVDES)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_STATIC_FMV)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_STATIC_MAF)->ShowWindow(SW_HIDE);

    m_lstDevices.ShowWindow(SW_HIDE);

    return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void COPOSADKDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}

void COPOSADKDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // 用于绘制的设备上下文

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // 使图标在工作区矩形中居中
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // 绘制图标
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR COPOSADKDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}


#include "DlgAddDevice.h"

void COPOSADKDlg::OnBnClickedBtnAdd()
{
    CDlgAddDevice dlg;

    dlg.SetRootKey(m_hRootKey);
    dlg.SetClassKey(m_hClassKey);

    if (IDOK == dlg.DoModal())
    {
        m_curdeviceDef = dlg.CurDeviceInfo();
        m_curdeviceDef.ePortType = EUSB;    // Default;
        // Add new LDN
        AddNewLDN();

        //AddDevBasicInfo()
        CString strDevFile = m_curdeviceDef.DeviceName + _T(".ini");
        AddDevBasicInfo(strDevFile);

    }

    m_treeDevices.DeleteAllItems();
    QueryDeviceName(_T(OPOS_CLASSKEY_SCAN));	

}


void COPOSADKDlg::OnBnClickedBtnCheck()
{    
#if 0
    CCheckDlg dlg;
    dlg.SetDeviceInfo(m_curdeviceDef);

    dlg.DoModal();
#endif
    
    m_pCheckDlg = new CCheckDlg();
    m_pCheckDlg->SetDeviceInfo(m_curdeviceDef);
    m_pCheckDlg->Create(IDD_DLG_CHECK);
    m_pCheckDlg->ShowWindow(SW_SHOWNORMAL);
}

//#include <stdlib.h>
#include <vector>
#include <map>
using namespace std;
int COPOSADKDlg::QueryDeviceName(const CString& strDeviceClass)
{
    long lRegStat = RegOpenKeyEx(
        HKEY_LOCAL_MACHINE,
        _T(OPOS_ROOTKEY),
        0,
        KEY_ALL_ACCESS,
        &m_hRootKey);
    if(lRegStat != ERROR_SUCCESS)
        return 1;

    TCHAR cClassKey[256];
    if (!strDeviceClass.IsEmpty())
    {
        if(0 == strDeviceClass.CompareNoCase( _T(OPOS_CLASSKEY_SCAN )))
            wcscpy(cClassKey,_T(OPOS_CLASSKEY_SCAN ));
        else
            return 2;
    }


    lRegStat = RegOpenKeyEx(m_hRootKey,
        cClassKey,
        0,
        KEY_ALL_ACCESS,
        &m_hClassKey);

    if (lRegStat != ERROR_SUCCESS) return 3;

    HTREEITEM hItemParent = NULL;
    map<CString, HTREEITEM> mapHTree;
    TCHAR szDeviceName[256];
    DWORD dwSize = 256;
    DWORD dwType = 0;
    TCHAR szKeyValue[256];

    int i = 0;
    while(i < 256)
    {
        lRegStat = RegEnumKeyEx(
            m_hClassKey,
            i,
            szDeviceName,
            &dwSize,
            0,
            NULL,
            NULL,
            NULL);

        if (lRegStat == ERROR_NO_MORE_ITEMS /*|| lRegStat == ERROR_SUCCESS*/) 
            break;

        hItemParent = m_treeDevices.InsertItem(szDeviceName);
        mapHTree[CString(szDeviceName)] = hItemParent;
        dwSize = 256;
        i++;
    }

    i = 0;
    DWORD dwNum = 256;
    while(i < 256)
    {
        lRegStat = RegEnumValue(
            m_hClassKey,
            i,
            cClassKey,
            &dwSize,
            0,
            &dwType,
            (unsigned char *)szKeyValue,
            &dwSize);

        if (lRegStat == ERROR_NO_MORE_ITEMS /*|| lRegStat == ERROR_SUCCESS*/) 
            break;

        hItemParent = mapHTree[CString(szKeyValue)];
        m_treeDevices.InsertItem(LPTSTR(cClassKey), hItemParent);

        i++;
        dwNum = 256;
        dwSize = 256;		
    }
    m_treeDevices.Expand(hItemParent,TVE_EXPAND);

    return 0;
}

int COPOSADKDlg::AddNewLDN()
{
    BOOL bExit = FALSE;
    TCHAR szDeviceNameKey[256];
    TCHAR szDeviceName[256] = _T("");
    DWORD dwSize = 256;
    int i = 0;
    long lRegStat;

    while(i < 256)
    {
        lRegStat = RegEnumKeyEx(m_hClassKey,
            i,
            szDeviceNameKey,
            &dwSize,
            0,
            NULL,
            NULL,
            NULL);

        if(lRegStat == ERROR_SUCCESS )
        {
            bExit = TRUE;

            // ZHW TODO
            break;
        }

        if(lRegStat == ERROR_NO_MORE_ITEMS) break;

        i++;
    }

    if (bExit)
    {
        // ZHW TODO
    }

    wcscpy(szDeviceName, m_curdeviceDef.DeviceName);
    lRegStat = RegSetValueEx(m_hClassKey,
        (LPCTSTR)m_curdeviceDef.DeviceLDN,
        0,
        REG_SZ,
        (unsigned char*)szDeviceName,
        256);

    if (lRegStat == ERROR_SUCCESS)
    {
        return 0;
    }
    else
        return 0;

}

int COPOSADKDlg::AddDevBasicInfo(const CString& strDefFile)
{
    long lRegStat = RegCreateKeyEx(
        m_hClassKey,
        (LPTSTR)(LPCTSTR)m_curdeviceDef.DeviceName,
        0,
        NULL,
        REG_OPTION_NON_VOLATILE,
        KEY_ALL_ACCESS,
        NULL,
        &m_hServiceKey,
        NULL);
    if(lRegStat != ERROR_SUCCESS)
    {
        return 1;
    }


    CString strFileName;
    DWORD dwSize = 256;
    strFileName = m_strADKInstallPath + HIT_OPOS_SYSTEM + strDefFile;

    TCHAR szSOName[256];
    memset(szSOName, 0, 256);

    GetPrivateProfileString(
        _T("Main"),
        _T("SOName"),
        NULL,
        szSOName,
        dwSize,
        strFileName);

    lRegStat = RegSetValueEx(
        m_hServiceKey,
        NULL,
        0,
        REG_SZ,
        /*(unsigned char *)*/(BYTE*)szSOName,
        256/*strlen(szSOName)*/);

    DWORD dwTemp;
    int i = 0;
    WCHAR szValue[256];
    memset(szValue, 0, 256*sizeof(WCHAR));
    dwSize = 256;

    WCHAR *cTemp[] = 
    {
        L"DeviceClass",
        L"DeviceName",
        L"DeviceDesc",
        L"GroupID",
        L"Comp",
        L"Version",	
        L"Connect"
    };

    while(i < 7)
    {
        dwTemp = GetPrivateProfileString(
            _T("Main"),
            cTemp[i],
            0,
            szValue,
            dwSize,
            strFileName);

        lRegStat = RegSetValueEx(
            m_hServiceKey,
            cTemp[i],
            0,
            REG_SZ,
            (unsigned char *)szValue,
            256/*wcslen(cValue)*/);		
        i++;
        dwSize = 256;
    }

    return 0;
}

int COPOSADKDlg::InitInstallPath()
{
    if (m_strADKInstallPath.GetLength() > 0)
        return 0;

    HKEY hBaseKey;
    long lRegStat = RegOpenKeyEx(
        HKEY_LOCAL_MACHINE,
        _T(OPOS_ROOTKEY_PROVIDER),
        0,
        KEY_ALL_ACCESS,
        &hBaseKey);
    if(lRegStat != ERROR_SUCCESS)
    {

#ifdef __DEBUG_LOG__
        Log(ERROR_LEVEL, EOPOSADK, wstring(_T("Get ADK installed path failed, can't find opos root key. ")));
#endif

        return 1;
    }

    HKEY hServiceKey;
    lRegStat = RegOpenKeyEx(
        hBaseKey,
        __ADK_PROVIDER__,
        0,
        KEY_ALL_ACCESS,
        &hServiceKey);
    RegCloseKey(hBaseKey);
    if(lRegStat != ERROR_SUCCESS)
        return -1;


    DWORD dwType,dwSize = MAX_PATH;
    TCHAR szInstallDir[MAX_PATH];
    lRegStat = RegQueryValueEx(
        hServiceKey,
        _T("Path"),
        0,
        &dwType,
        (unsigned char*)szInstallDir,
        &dwSize);
    if(lRegStat != ERROR_SUCCESS && dwType != REG_SZ)
    {
#ifdef __DEBUG_LOG__
        Log(ERROR_LEVEL, EOPOSADK, wstring(_T("Fail to get OPOS installed path. ")));
#endif
        return 2;
    }

    m_strADKInstallPath = szInstallDir;
    RegCloseKey(hServiceKey);

#ifdef __DEBUG_LOG__
    LOG_INFO(wstring(_T("OPOS ADK installed path : ")) + wstring(m_strADKInstallPath));
#endif

    return 0;
}

void COPOSADKDlg::UpdateSelectedDeviceInfo()
{
    TCHAR szKeyValue[256];
    DWORD dwType;
    DWORD dwNum = 256;
    DWORD dwSize = 256;
    TCHAR szClassKey[256];

    GetDlgItem(IDC_STATIC_DEVLDN)->SetWindowText(_T("Device LDN: ") + m_curdeviceDef.DeviceLDN);
    GetDlgItem(IDC_STATIC_DEVLDN)->ShowWindow(SW_SHOW);

    GetDlgItem(IDC_STATIC_DEVNAME)->SetWindowText(_T("Device Name: ") + m_curdeviceDef.DeviceName);
    GetDlgItem(IDC_STATIC_DEVNAME)->ShowWindow(SW_SHOW);

    if (!m_curdeviceDef.DeviceClass.IsEmpty())
    {
        if(0 == m_curdeviceDef.DeviceClass.CompareNoCase( _T(OPOS_CLASSKEY_CASH )))
            wcscpy(szClassKey,_T(OPOS_CLASSKEY_CASH ));
        else if(0 == m_curdeviceDef.DeviceClass.CompareNoCase( _T(OPOS_CLASSKEY_PTR )))
            wcscpy(szClassKey, _T(OPOS_CLASSKEY_PTR ) );
        else if(0 == m_curdeviceDef.DeviceClass.CompareNoCase(_T(OPOS_CLASSKEY_DISP )))
            wcscpy(szClassKey,_T(OPOS_CLASSKEY_DISP ) );
        else if (0 == m_curdeviceDef.DeviceClass.CompareNoCase(_T(OPOS_CLASSKEY_SCAN )))
        {
            wcscpy(szClassKey, _T(OPOS_CLASSKEY_SCAN));
        }
        else return;
    }

    long lRet = RegOpenKeyEx(m_hRootKey, szClassKey,0,KEY_ALL_ACCESS,&m_hClassKey);
    if (lRet != ERROR_SUCCESS)
        return;

    int i = 0;
    long lRegStat = ERROR_SUCCESS;

    wcscpy(szKeyValue, m_curdeviceDef.DeviceName);
    lRegStat  = RegOpenKeyEx(
        m_hClassKey,
        szKeyValue,
        0,
        KEY_ALL_ACCESS,
        &m_hServiceKey);
    if(lRegStat != ERROR_SUCCESS)
        return;

    lRegStat = RegQueryValueEx(m_hServiceKey,_T("DeviceDesc"),0,&dwType,(LPBYTE)szKeyValue,&dwSize);
    if(lRegStat != ERROR_SUCCESS || dwType != REG_SZ)
        m_curdeviceDef.DeviceDesc = _T("NONE");
    else
        m_curdeviceDef.DeviceDesc = szKeyValue;
    GetDlgItem(IDC_STATIC_DEVDES)->SetWindowText(_T("Description:  ") + m_curdeviceDef.DeviceDesc);
    GetDlgItem(IDC_STATIC_DEVDES)->ShowWindow(SW_SHOW);

    lRegStat = RegQueryValueEx(m_hServiceKey,_T("Version"),0,&dwType,(LPBYTE)szKeyValue,&dwSize);
    if(lRegStat != ERROR_SUCCESS || dwType != REG_SZ)
        m_curdeviceDef.FirmwareVer = _T("NONE");
    else
        m_curdeviceDef.FirmwareVer = szKeyValue;
    GetDlgItem(IDC_STATIC_FMV)->SetWindowText(_T("FirmWare Version:  ") + m_curdeviceDef.FirmwareVer);
    GetDlgItem(IDC_STATIC_FMV)->ShowWindow(SW_SHOW);

    lRegStat = RegQueryValueEx(m_hServiceKey,_T("Comp"),0,&dwType,(LPBYTE)szKeyValue,&dwSize);
    if(lRegStat != ERROR_SUCCESS || dwType != REG_SZ)
        m_curdeviceDef.Manufacture = _T("NONE");
    else
        m_curdeviceDef.Manufacture = szKeyValue;
    GetDlgItem(IDC_STATIC_MAF)->SetWindowText(_T("Manufacture:  ") + m_curdeviceDef.Manufacture);
    GetDlgItem(IDC_STATIC_MAF)->ShowWindow(SW_SHOW);

}

int COPOSADKDlg::CheckDeviceVendorInfo(CString &strVendor)
{
    TCHAR szTemp[256];
    DWORD dwType = 0;
    DWORD dwSize = 256;
    long lRet = RegQueryValueEx(
        m_hServiceKey, 
        TEXT("Comp"),
        NULL,
        &dwType,
        (LPBYTE)szTemp,
        &dwSize
        );

    if (lRet != ERROR_SUCCESS || dwType != REG_SZ)
    {
        // zhwang Add Log
        return 1;
    }

    strVendor = szTemp;

    return 0;
}

void COPOSADKDlg::OnTvnSelchangedTreeDevices(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);

    HTREEITEM hSelItem = m_treeDevices.GetSelectedItem();
    HTREEITEM hParentItem = m_treeDevices.GetParentItem(hSelItem);
    HTREEITEM hChildItem = m_treeDevices.GetChildItem(hSelItem);

    if (NULL != hParentItem && NULL == hChildItem)
    {
        m_curdeviceDef.DeviceLDN = m_treeDevices.GetItemText(hSelItem);
        m_curdeviceDef.DeviceName = m_treeDevices.GetItemText(hParentItem);
        m_curdeviceDef.DeviceClass = L"Scanner";

        UpdateSelectedDeviceInfo();

        GetDlgItem(IDC_BTN_CHECK)->EnableWindow(TRUE);
        GetDlgItem(IDC_BTN_DELETE)->EnableWindow(TRUE);
    }
    else
    {
        m_curdeviceDef.DeviceClass.Empty();
        m_curdeviceDef.DeviceDesc.Empty();
        m_curdeviceDef.DeviceLDN.Empty();
        m_curdeviceDef.DeviceName.Empty();
        GetDlgItem(IDC_BTN_DELETE)->EnableWindow(FALSE);
        GetDlgItem(IDC_BTN_CHECK)->EnableWindow(FALSE);
    }

    *pResult = 0;
}


void COPOSADKDlg::OnBnClickedBtnDelete()
{

    CString strTemp;
    int nRet = CheckDeviceVendorInfo(strTemp);
    if (0 != nRet)
    {
        MessageBox(L"Fail to get device information!", L"Error", MB_OK|MB_ICONERROR);
        return;
    }

    if(strTemp.Left(9) != L"Honglitek")
    {
        MessageBox(_T("This device is not a Honglitek device!"), L"Attention", MB_OK|MB_ICONWARNING);
        return;
    }

    strTemp = L"Are you sure to delete " + m_curdeviceDef.DeviceLDN;
    strTemp.Append(_T("?"));
    if (IDCANCEL == MessageBox(strTemp, L"Attention", MB_OKCANCEL|MB_ICONWARNING))
        return;

    LONG lRet = RegDeleteValue(m_hClassKey, m_curdeviceDef.DeviceLDN);
    if (lRet != ERROR_SUCCESS)
    {
        // zhwang Add log
    }

#if 0
    lRet = RegDeleteKey(m_hClassKey, (LPCTSTR)m_curdeviceDef.DeviceName);
    if (ERROR_SUCCESS != lRet)
    {
        zhwang Add log
    }
#endif

    m_treeDevices.DeleteAllItems();
    QueryDeviceName(_T(OPOS_CLASSKEY_SCAN));	

}


void COPOSADKDlg::OnNMClickSyslink1(NMHDR *pNMHDR, LRESULT *pResult)
{
    PNMLINK pNMLink = (PNMLINK) pNMHDR;   

    ShellExecuteW(NULL, L"open", VENDOR_WEB_SITE, NULL, NULL, SW_SHOWNORMAL);  

    *pResult = 0;
}
